package com.monster.datasourcejob.metadata.impl;

import com.monster.datasourcejob.model.Field;
import com.monster.datasourcejob.metadata.MetaDataDriver;
import com.monster.datasourcejob.model.Table;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;


/**
 * description:
 *
 * @author Yuanml on 2021/6/28 16:39
 */
public class MysqlMetaDataDriver implements MetaDataDriver {
    private static final Logger LOGGER = LoggerFactory.getLogger(MysqlMetaDataDriver.class);
    private static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
    private String password;
    private String url;
    private String username;
    private static final String SQL = "SHOW FULL COLUMNS FROM ";
    private static final String CREATE_SQL = "SHOW CREATE TABLE ";

    static {
        try {
            Class.forName(DRIVER_NAME);
        } catch (ClassNotFoundException e) {
            LOGGER.error("加载驱动出错", e);
        }
    }

    public MysqlMetaDataDriver(String url, String username, String password) {
        this.password = password;
        this.url = url;
        this.username = username;
    }

    private Connection getConnection() {
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            LOGGER.error("获取mysql连接出错，url：{}，username：{}，pwd：{}", url, username, password);
        }
        return conn;
    }

    private void closeConnection(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                LOGGER.error("关闭mysql连接出错", e);
            }
        }
    }

    @Override
    public List<Table> getTables() {
        List<Table> res = null;
        try (Connection connection = getConnection()) {
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet tables = metaData.getTables(null, null, null, new String[]{"TABLE"});
            res = new ArrayList<>(tables.getFetchSize());
            while (tables.next()) {
                res.add(new Table(tables.getString(3)));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return res;
    }

    @Override
    public List<Field> getFields(String tableName) {
        if (StringUtils.isBlank(tableName)) {
            throw new IllegalArgumentException("参数【tableName】不能为空");
        }
        List<Field> res = null;
        try (Connection connection = getConnection()) {
            String sql = SQL + tableName;
            ResultSet resultSet = connection.prepareStatement(sql).executeQuery();
            int fetchSize = resultSet.getFetchSize();
            res = new ArrayList<>(fetchSize);
            while (resultSet.next()) {
                res.add(new Field(
                        resultSet.getString("Field"),
                        resultSet.getString("Type"),
                        resultSet.getString("Comment")
                ));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return res;
    }

    @Override
    public String getTableBuildingSql(String tableName) {
        if (StringUtils.isBlank(tableName)) {
            throw new IllegalArgumentException("参数【tableName】不能为空");
        }
        try (Connection connection = getConnection()) {
            String sql = CREATE_SQL + tableName;
            ResultSet resultSet = connection.prepareStatement(sql).executeQuery();
            String result = "";
            while (resultSet.next()) {
                result = resultSet.getString("Create Table");
            }
            return result;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return "";
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}
